from ctypes import *
libc = cdll.msvcrt

class POINT(Structure):
    _fields_ = [("x", c_int), ("y", c_int)]
    
class RECT(Structure):
    _fields_ = [("upperleft", POINT), ("lowerright", POINT)]
    
#point = POINT(10, 20)
#print(point.x, point.y)

r = RECT(POINT(1,2), POINT(3,4))
print(r.upperleft.x, r.upperleft.y, r.lowerright.x, r.lowerright.y)
print(POINT.x)

class Int(Structure):
    _fields_ = [("first_16", c_int, 16), ("second_16", c_int, 16)]
class UByte(Structure):
    _fields_ = [("first_4", c_ubyte, 4), ("second_4", c_ubyte, 4)]
    
print(sizeof(Int), Int.second_16)
print(sizeof(UByte), UByte.first_4)

class MyStruct(Structure):
    _fields_=[("a", c_int), ("b", c_float), ("point_array", POINT*4)]
    
print(sizeof(MyStruct), sizeof(POINT),len(MyStruct().point_array))

TenPointsArrayType = POINT * 10

arr = TenPointsArrayType()
for pt in arr:
    print(pt.x, pt.y)
    
TenIntegers = c_int * 10
ii = TenIntegers(1,2,3,4,5,6,7,8,9,10)
for i in ii:
    print(i,end=" ")
print("\n", end="")    
i = c_int(42)
pi = pointer(i)
print(pi.contents)
j = c_int(99)
pi.contents = j
print(pi.contents)
j.value = 44
print(pi.contents)

class Bar(Structure):
    _fields_ = [("count", c_int), ("values", POINTER(c_int))]
    
bar = Bar()
#bar.values = (c_int * 3)(1,2,3)
#bar.count = 3

#for i in range(bar.count):
    #print(bar.values[i], end=" ")
#print("\n", end="")

bar.values = cast((c_byte * 4)(), POINTER(c_int))
bar.values[0] = 200
print(bar.values[0])

"""
struct cell;
struct cell {
    char * name;
    struct cell * next;
};
"""

class cell(Structure):
    pass

cell._fields_ = [("name", c_char_p), ("next", POINTER(cell))]

c1 = cell()
c1.name = b"foo"

c2 = cell()
c2.name = b"bar"
c1.next = pointer(c2)
c2.next = pointer(c1)

p = c1
for i in range(8):
    print(p.name, end=" ")
    p = p.next.contents
print("\n", end="")
IntArray5 = c_int * 5
ia = IntArray5(5, 1, 7, 33, 99)

# void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
qsort = libc.qsort
qsort.restype = None

CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
def py_cmp_func(a, b):
    return a.contents.value > b.contents.value

cmp_func = CMPFUNC(py_cmp_func)
qsort(ia, len(ia), sizeof(c_int), cmp_func)

for i in range(len(ia)):
    print(ia[i], end=" ")
    
class struct_frozen(Structure):
    _fields_ = [("name", c_char_p), ("code", POINTER(c_ubyte)), ("size", c_int)]
    
FrozenTable = POINTER(struct_frozen)
table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
for item in table:
    print(item.name, item.size)
    if item.name is None:
        break
    